package com.mingqijia.gassafety.shared.jwt;

import com.mingqijia.gassafety.shared.constant.Constants;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.spec.SecretKeySpec;
import java.io.Serializable;
import java.security.Key;
import java.time.Instant;
import java.util.Date;
import java.util.Objects;

/**
 * Jwt Token功能处理类
 * @author Damon S.
 * @version v1.0.1
 * @date 2020年07月27日 23:21
 */
@Component
public class JwtProvider implements Serializable {
    private static final long serialVersionUID = -3301605591108950415L;

    @Value("${jwt.secret}")
    private String secret;

    @Value("${jwt.expiration}")
    private Integer expiresIn;

    public String generateToken(JwtAware jwtInfo) {
        Integer expiredDuration = expiresIn;
        if (Objects.nonNull(jwtInfo.getExpiredIn())) {
            expiredDuration = jwtInfo.getExpiredIn();
        }
        final Date expiredAt = Date.from(
                Instant.now().plusSeconds(expiredDuration)
        );
        return Jwts.builder().setExpiration(expiredAt)
                .setSubject(jwtInfo.getUniqueName())
                .signWith(createSecretKey()).compact();
    }

    public JwtAware parseToken(String token) {
        String pureToken = token.startsWith(Constants.PREFIX_BEARER)
                ? token.replace(Constants.PREFIX_BEARER, Constants.STR_EMPTY)
                : token;
        final Claims body = Jwts.parserBuilder()
                .setSigningKey(createSecretKey())
                .build().parseClaimsJws(pureToken)
                .getBody();
        return JwtToken.builder().expiredAt(body.getExpiration())
                .uniqueName(body.getSubject()).build();
    }

    public boolean tokenExpired(JwtAware token) {
        return Date.from(Instant.now()).after(token.getExpiredAt());
    }

    private Key createSecretKey() {
        return new SecretKeySpec(secret.getBytes(), SignatureAlgorithm.HS512.getJcaName());
    }
}
